#include <algorithm>
#include <cmath>
#include <iostream>
#include <variant>
#include <vector>
using namespace std;

// 用来存放一元二次方程的解，无实根，有一个根，有两个根
using Two = std::pair<double, double>;
using Roots = std::variant<Two, double, nullptr_t>;

// ax^2 +bx^1+cx^0 = 0;
// 传参为一元二次方程的系数 a,b,c
Roots FindRoots(double a, double b, double c)
{
    // 一元二次方程的求根公式
    if (const auto d = b * b - 4 * a * c; d > 0.0)
    {
        const auto p = sqrt(d);
        return std::make_pair((-b + p) / 2 * a, (-b - p) / 2 * a);
    }
    else if (d == 0.0)
    {
        return (-1 * b) / (2 * a);
    }
    return nullptr;
}

struct RootPrinterVisitor
{
    void operator()(const Two& roots) const { std::cout << "2 roots: " << roots.first << " " << roots.second << '\n'; }
    void operator()(const double root) const { std::cout << "1 root: " << root << '\n'; }
    void operator()(nullptr_t) const { std::cout << "No real roots found.\n"; }
};
void test_roots()
{
    std::visit(RootPrinterVisitor(), FindRoots(1, -2, 1)); //(x-1)*(x-1)=0   有一个根
    std::visit(RootPrinterVisitor(), FindRoots(1, -3, 2)); //(x-2)*(x-1)=0   有两个根
    std::visit(RootPrinterVisitor(), FindRoots(1, 0, -2)); // x*x - 2 = 0    有两个根
    std::visit(RootPrinterVisitor(), FindRoots(1, 0, +2)); // x*x + 2 = 0    无实根
}

struct Triangle
{
    static void Draw() { std::cout << "Triangle" << std::endl; }
};

struct Circle
{
    static void Draw() { std::cout << "Circle" << std::endl; }
};

void test_triangle()
{
    using Draw = std::variant<Triangle, Circle>;

    const std::vector<Draw> draw_list{Triangle{}, Circle{}, Triangle{}};
    auto DrawVisitor = [](const auto& t) { t.Draw(); };
    for (const auto& item : draw_list)
    {
        std::visit(DrawVisitor, item);
    }
}
int main(int argc, char const* argv[])
{
    test_roots();
    test_triangle();
    return 0;
}
